Stop documenting the workspace anon key as a browser build arg - #19
Open
schlunsen wants to merge 1 commit into
Open
Stop documenting the workspace anon key as a browser build arg#19schlunsen wants to merge 1 commit into
schlunsen wants to merge 1 commit into
Conversation
The skill told apps to pass the workspace Supabase anon key as
`VITE_SUPABASE_ANON_KEY` via `--build-arg`, for "frontend-only apps
using the anon key". Both halves of that are wrong on n0.
A `--build-arg` feeding a `VITE_*` variable is not a secret: Vite inlines
it into the JS bundle, so it ships to every visitor in plain text.
And the anon key here is workspace-wide, not per-app. Vanilla Supabase
scopes its anon key to a single project, which is what makes the usual
"anon key in the browser + RLS" advice sound; on n0 one key spans every
app's `app_*` schema and every member's private `u_*` schema on the
instance. The upstream reasoning does not carry over, and the blast
radius is the whole workspace. This has already produced one incident,
where data in a private schema was published via a grant to `anon`.
Replace the section with the rule instead — the database is never
queried from the browser, always through a backend — and drop the anon
key from the Dockerfile and CI templates, leaving only genuinely public
build args. Also flag it at the two other places it was reachable: the
App Data env table, and the quick-reference that told you to fetch
workspace credentials and run app migrations through
`/workspaces/{id}/supabase/sql/` (admin-only, superuser, `public`
schema, and not replayed on a fresh deploy). App schemas come from
committed `migrations/*.sql`.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The skill instructed apps to pass the workspace Supabase anon key as
VITE_SUPABASE_ANON_KEYthrough--build-arg, described as the approach for "frontend-only apps using the anon key". Both halves of that are wrong on n0.A build arg feeding a
VITE_*variable is not a secret. Vite inlines it into the JS bundle, so it is served to every visitor in plain text and readable with View Source.The anon key here is workspace-wide, not per-app. Vanilla Supabase scopes its anon key to a single project, which is what makes the usual "anon key in the browser + RLS" advice sound. On n0, one key spans every app's
app_*schema and every member's privateu_*schema on the instance — so the upstream reasoning does not carry over and the blast radius is the whole workspace. This has already produced one incident, where data in a privateu_*schema was published via a grant toanon.The rule is: the database is never queried directly from the browser, always through a backend.
app_data: truealready gives an app server-sideN0_APP_SUPABASE_*credentials at runtime, scoped to its own schema, which is the supported path.Changes
VITE_SUPABASE_URL/VITE_SUPABASE_ANON_KEYfrom the Dockerfile and CI workflow templates, leaving only genuinely public build args, plus a note that a build arg is not a secret.VITE_-shaped temptation — clarified that it is only Kong's gateway header, not what authorises the app;.envand run app migrations viaPOST /workspaces/{id}/supabase/sql/. That endpoint is workspace-admin-only, runs assupabase_admin(a Postgres superuser) against the sharedpublicschema, and is not replayed on a fresh deploy. App schemas belong in committedmigrations/*.sql.Verification
I scanned the deployed apps on Moon before writing this: 34 apps enumerated, 6 publicly reachable (the rest sit behind n0 SSO), all 6 deep-scanned including nested chunk imports — no anon keys found in any bundle. So this documents a trap nobody has stepped in yet rather than cleaning up after a leak. The private-schema incident referenced above came through the agent SQL tool, not through a bundle.
No corresponding change is needed in
README.md— it does not mention the pattern.